// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Regular_triangulation_2.cpp 167 2007-11-02 15:36:54Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Triangulations_2/Py_Regular_triangulation_2.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================

// include ====================================================================
#include <include/Kernels.h>
#include <include/iterator.h>

#include <CGAL/Regular_triangulation_2.h>
#include <CGAL/Regular_triangulation_euclidean_traits_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_data_structure_2.h>
#include "Py_Regular_Triangulation_2_doc.h"

#include <boost/python.hpp>
#include <boost/cstdint.hpp>


using namespace boost::python;
using boost::python::object;
namespace  {

	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(is_valid_overloads_0_2, is_valid, 0, 2)
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(insert_overloads_1_2, insert, 1, 2)
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(remove_degree_3_overloads_1_2, remove_degree_3, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(locate_overloads_3_4, locate, 3, 4)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(locate_overloads_1_2, locate, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(incident_faces_overloads_1_2, incident_faces, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(incident_vertices_overloads_1_2, incident_vertices, 1, 2)	
	BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(incident_edges_overloads_1_2, incident_edges, 1, 2)	
//	BOOST_PYTHON_FUNCTION_OVERLOADS(line_walk_overloads_2_3, py_line_walk, 2, 3)

}// namespace 
//BEGIN=========================Insert a list of Weighted points=====================
template <class Triangulation>
int py_insert(Triangulation& rt,boost::python::list pts)
{
	typedef typename Triangulation::Weighted_point Weighted_point;
	int nb_points = 0;

	for(int i = 0 ; i < pts.attr("__len__")() ; i++)
	{
		Weighted_point P = boost::python::extract<Weighted_point>(pts[i]); 
		rt.insert(P);
		nb_points++;
	}
	return nb_points;
}
//END=========================Insert a list of Weighted points=====================

//BEGIN ======================dual function ===============================

template <class kernel,class Regular_triangulation_2,class Edge>
object dual(const Regular_triangulation_2& rt,const Edge& e)
{
	//three cases are possible:
	typedef typename kernel::Ray_2 			Ray_2;
	typedef typename kernel::Segment_2 		Segment_2;
	typedef typename kernel::Line_2 		Line_2;

	CGAL::Object o = rt.dual(e);
	Ray_2 r;
	Segment_2 s;
	Line_2 l;
	object obj;
	if( CGAL::assign(r,o) ) return object(r);
	else if(CGAL::assign(s,o)) return object(s);
	else {CGAL::assign(l,o);  return object(l);}	
	
}
//END ======================dual function  ===============================

//BEGIN=========================getter conflicts and hidden_vertices functions===============
//===============get_conflicts
template <class Regular_triangulation_2,class Point_2,class Face_handle>
boost::python::list py_get_conflicts(const Regular_triangulation_2& rt,Point_2 pt,Face_handle start)
{
	boost::python::list result;
	std::list<Face_handle>  liste;
	rt.get_conflicts(pt,std::back_inserter(liste),start);
	typename std::list<Face_handle>::iterator iter;

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);
	
	return result;
}
//===============get_boundary_of_conflicts
template <class Regular_triangulation_2,class Point_2,class Face_handle,class Edge>
boost::python::list py_get_boundary_of_conflicts(const Regular_triangulation_2& rt,Point_2 pt,Face_handle start)
{
	boost::python::list result;
	std::list<Edge>  liste;
	typename std::list<Edge>::iterator iter;

	rt.get_boundary_of_conflicts(pt,std::back_inserter(liste),start);

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);
	
	return result;

}
//===============get_hidden_vertices
template <class Regular_triangulation_2,class WPoint_2,class Face_handle>
boost::python::list py_get_hidden_vertices(const Regular_triangulation_2& rt,WPoint_2 pt,Face_handle start)
{
	boost::python::list result;
	typedef typename Regular_triangulation_2::Vertex_handle Vertex_handle;
	std::list<Vertex_handle> liste;
	typename std::list<Vertex_handle>::iterator iter;
	rt.get_hidden_vertices(pt, std::back_inserter(liste),start);

	for(iter = liste.begin(); iter != liste.end(); iter++)
		result.append(*iter);
	
	return result;

}
template < class Regular_triangulation_2,class Face_handle,class Point_2>
Face_handle py_locate(Regular_triangulation_2& tri,Point_2 pt,boost::python::list& liste/*,Face_handle fh = Face_handle()*/)
{
	Face_handle result;
	typedef typename Regular_triangulation_2::Locate_type Locate_type;
	Locate_type lt;
	int ti;
	int N = boost::python::extract<int>(liste.attr("__len__")());
	if (N >= 1) for(int i = 0 ; i < N ; i++) liste.remove(liste[0]);

	result = tri.locate(pt,lt,ti);
	liste.append(lt);
	liste.append(ti);
	return result;
}

//END=========================getter conflicts and hidden_vertices functions===============

//BEGIN=========================finites_vertices and hidden_vertices=====================
template < class iterator,class Vertex_handle,class Triangulation>
Handle_to_py_iterator<iterator,Vertex_handle> py_vertices(const Triangulation& rt)
{
	std::pair< iterator , iterator > p( rt.finite_vertices_begin(), rt.finite_vertices_end() );
	return Handle_to_py_iterator<iterator,Vertex_handle>(p);
}

template < class iterator,class Vertex_handle,class Triangulation>
Handle_to_py_iterator<iterator,Vertex_handle> py_hidden_vertices(const Triangulation& rt)
{
	std::pair< iterator , iterator > p( rt.hidden_vertices_begin(), rt.hidden_vertices_end() );
	return Handle_to_py_iterator<iterator,Vertex_handle>(p);
}

template < class iterator,class Vertex_handle,class Triangulation>
Handle_to_py_iterator<iterator,Vertex_handle> py_all_vertices(const Triangulation& rt)
{
	std::pair< iterator , iterator > p( rt.all_vertices_begin(), rt.all_vertices_end() );
	return Handle_to_py_iterator<iterator,Vertex_handle>(p);
}
//END=========================finites_vertices and hidden_vertices=====================

//BEGIN ===========Face, Edge and Vertex Circulators=====================
template < class Circulator,class Face_handle,class Vertex_handle,class Triangulation>
circulator_to_py_iterator<Circulator,Face_handle> py_incident_faces(const Triangulation& rt,Vertex_handle v)
{
	Circulator first = rt.incident_faces(v),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Face_handle>(p);
}
template < class Circulator,class Vertex_handle,class Face_handle,class Triangulation>
circulator_to_py_iterator<Circulator,Face_handle> py_incident_faces_2(const Triangulation& rt,Vertex_handle v,Face_handle f)
{
	Circulator first = rt.incident_faces(v,f),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Face_handle>(p);
}

template < class Circulator,class Vertex_handle,class Triangulation>
simple_python_circulator<Circulator> py_incident_edges(const Triangulation& rt,Vertex_handle v)
{
	Circulator first = rt.incident_edges(v),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);

}
template < class Circulator,class Vertex_handle,class Face_handle,class Triangulation>
simple_python_circulator<Circulator> py_incident_edges_2(const Triangulation& rt,Vertex_handle v,Face_handle f)
{
	Circulator first = rt.incident_edges(v,f),last;
	std::pair< Circulator , Circulator > p( first, last);
	return simple_python_circulator<Circulator>(p);
}

template < class Circulator,class Vertex_handle,class Triangulation>
circulator_to_py_iterator<Circulator,Vertex_handle> py_incident_vertices(const Triangulation& rt,Vertex_handle v)
{
	Circulator first = rt.incident_vertices(v),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Vertex_handle>(p);
}

template < class Circulator,class Vertex_handle,class Face_handle,class Triangulation>
circulator_to_py_iterator<Circulator,Vertex_handle> py_incident_vertices_2(const Triangulation& rt,Vertex_handle v,Face_handle f)
{
	Circulator first = rt.incident_vertices(v,f),last;
	std::pair< Circulator , Circulator > p( first, last);
	return circulator_to_py_iterator<Circulator,Vertex_handle>(p);
}

template < class circulator,class Point_2,class Triangulation>
boost::python::list py_line_walk(Triangulation& dt,Point_2 p,Point_2 q)
{
	boost::python::list result;
	circulator cir = dt.line_walk(p,q);
	circulator first = cir;
	if (!cir.is_empty())
	{
		do{
			result.append((first++).handle());
		}
		while( first != cir );
	}
	return result;
}


template < class circulator,class Point_2,class Face_handle,class Triangulation>
boost::python::list py_line_walk_2(Triangulation& dt,Point_2 p,Point_2 q,Face_handle f)
{
	boost::python::list result;
	circulator cir = dt.line_walk(p,q,f);
	circulator first = cir;
	if (!cir.is_empty())
	{
		do{
			result.append((first++).handle());
		}
		while( first != cir );
	}
	return result;
}

//END  ===========Face, Edge and Vertex Circulators=====================

//BEGIN ======================functions of Vertex Class ===============================
template <class Vertex_handle> 
object point(const Vertex_handle& vh)
{
	return object(vh->point());
}
template <class Vertex_handle> 
object py_info(const Vertex_handle& vh)
{
	return object(vh->info());
}
template <class Vertex_handle> 
void set_info(Vertex_handle& vh,const object& py_obj)
{
	vh->info() = py_obj;
}
template <class Vertex_handle,class Point_2> 
void set_point(Vertex_handle& vh,const Point_2& pt)
{
	vh->set_point(pt);
}
template <class Vertex_handle> 
void is_valid(const Vertex_handle& vh)
{
	vh->is_valid();
}
template <class Vertex_handle> 
int degree(const Vertex_handle& vh)
{
	return vh->degree();
}
//END ======================functions of Vertex Class ===============================

//BEGIN ======================functions of Face Class ===============================

template <class Face_handle> 
int py_ccw(const Face_handle& fh,int i)
{
	return fh->ccw(i);
}
template <class Face_handle> 
int py_cw(const Face_handle& fh,int i)
{
	return fh->cw(i);
}
template <class Face_handle,class Vertex_handle> 
Vertex_handle py_mirror_vertex(const Face_handle& fh,int i)
{
	return fh->mirror_vertex(i);
}
template <class Face_handle> 
int py_mirror_index(const Face_handle& fh,int i)
{
	return fh->mirror_index(i);
}
template <class Face_handle,class Vertex_handle> 
Vertex_handle py_vertex(const Face_handle& fh,int i)
{
	return fh->vertex(i);
}
template <class Face_handle,class Vertex_handle> 
bool py_has_vertex1(const Face_handle& fh,Vertex_handle v)
{
	return fh->has_vertex(v);
}
template <class Face_handle,class Vertex_handle> 
bool py_has_vertex2(const Face_handle& fh,Vertex_handle v,int i)
{
	return fh->has_vertex(v,i);
}
template <class Face_handle,class Vertex_handle> 
int py_index1(const Face_handle& fh,Vertex_handle v)
{
	return fh->index(v);
}
template <class Face_handle> 
int py_index2(const Face_handle& fh,Face_handle f)
{
	return fh->index(f);
}
template <class Face_handle> 
Face_handle py_neighbor(const Face_handle& fh,int i)
{
	return fh->neighbor(i);
}
template <class Face_handle> 
bool py_has_neighbor1(const Face_handle& fh,Face_handle f)
{
	return fh->has_neighbor(f);
}
template <class Face_handle> 
bool py_has_neighbor2(const Face_handle& fh,Face_handle f,int i)
{
	return fh->has_neighbor(f,i);
}
template <class Face_handle> 
void py_set_vertices1(Face_handle& fh)
{
	fh->set_vertices();
}
template <class Face_handle,class Vertex_handle> 
void py_set_vertices2(Face_handle& fh,Vertex_handle v1,Vertex_handle v2,Vertex_handle v3)
{
	fh->set_vertices(v1,v2,v3);
}
template <class Face_handle,class Vertex_handle> 
void py_set_vertex(Face_handle& fh,int i,Vertex_handle v)
{
	fh->set_vertex(i,v);
}
template <class Face_handle> 
void py_set_neighbor(Face_handle& fh,int i,Face_handle n)
{
	fh->set_neighbor(i,n);
}
template <class Face_handle> 
void py_set_neighbors1(Face_handle& fh)
{
	fh->set_neighbors();
}
template <class Face_handle> 
void py_set_neighbors2(Face_handle& fh,Face_handle n0, Face_handle n1, Face_handle n2)
{
	fh->set_neighbors(n0,n1,n2);
}
template <class Face_handle> 
void py_reorient(Face_handle& fh)
{
	fh->reorient();
}
template <class Face_handle> 
void py_ccw_permute(Face_handle& fh)
{
	fh->ccw_permute();
}
template <class Face_handle> 
void py_cw_permute(Face_handle& fh)
{
	fh->cw_permute();
}
template <class Face_handle> 
int py_dimension(Face_handle& fh)
{
	return fh->dimension();
}
//END ======================functions of Face Class ===============================

template < class iterator,class Handle,class Triangulation>
Handle_to_py_iterator<iterator,Handle> py_faces(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.finite_faces_begin(), tr.finite_faces_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
template < class iterator,class Handle,class Triangulation>
Handle_to_py_iterator<iterator,Handle> py_all_faces(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.all_faces_begin(), tr.all_faces_end() );
	return Handle_to_py_iterator<iterator,Handle>(p);
}
template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_edges(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.finite_edges_begin(), tr.finite_edges_end() );
	return simple_python_iterator<iterator>(p);
}
template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_all_edges(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.all_edges_begin(), tr.all_edges_end() );
	return simple_python_iterator<iterator>(p);
}

template < class iterator,class Triangulation>
simple_python_iterator<iterator> py_points(Triangulation& tr)
{
	std::pair< iterator , iterator > p( tr.points_begin(), tr.points_end() );
	return simple_python_iterator<iterator>(p);
}

// the wrapper of the Regular_triangulation_2 class. 
template < typename kernel>
void Py_Regular_triangulation_2()
{
	typedef CGAL::Triangulation_vertex_base_with_info_2<boost::python::object,kernel> 	Vb;
	typedef CGAL::Triangulation_face_base_2<kernel> 									Fb;
	typedef CGAL::Regular_triangulation_euclidean_traits_2<kernel,double>				Gt;
	typedef CGAL::Regular_triangulation_vertex_base_2<Gt,Vb> 							RVb;
	typedef CGAL::Regular_triangulation_face_base_2<Gt,Fb> 								RFb;

	typedef CGAL::Triangulation_data_structure_2<RVb,RFb> 								Tds;

	typedef CGAL::Regular_triangulation_2<Gt,Tds>   						Regular_triangulation_2;

	typedef typename Regular_triangulation_2::Weighted_point 				Weighted_point;
	typedef typename Regular_triangulation_2::Point_iterator 				Point_iterator;

	typedef typename Regular_triangulation_2::Finite_vertices_iterator 		Finite_vertices_iterator;
	typedef typename Regular_triangulation_2::Face_iterator 				Face_iterator;
	typedef typename Regular_triangulation_2::Finite_faces_iterator 		Finite_faces_iterator;
	typedef typename Regular_triangulation_2::Face_handle 					Face_handle;
	typedef typename Regular_triangulation_2::Face_circulator 				Face_circulator;
	typedef typename Regular_triangulation_2::Line_face_circulator			Line_face_circulator;

	typedef typename Regular_triangulation_2::All_vertices_iterator 		All_vertices_iterator;
	typedef typename Regular_triangulation_2::All_faces_iterator 	    	All_faces_iterator;
	typedef typename Regular_triangulation_2::Vertex_handle 				Vertex_handle;
	typedef typename Regular_triangulation_2::Vertex_iterator 				Vertex_iterator;
	typedef typename Regular_triangulation_2::Hidden_vertices_iterator		Hidden_vertices_iterator;
	typedef typename Regular_triangulation_2::Vertex_circulator				Vertex_circulator;

	typedef typename Regular_triangulation_2::Edge 							Edge;
	typedef typename Regular_triangulation_2::All_edges_iterator			All_edges_iterator;
	typedef typename Regular_triangulation_2::Finite_edges_iterator			Finite_edges_iterator;
	typedef typename Regular_triangulation_2::Edge_circulator				Edge_circulator;
	typedef typename Regular_triangulation_2::Edge_iterator			  		Edge_iterator;

	typedef typename kernel::Point_2 										Point_2;
	typedef typename kernel::Segment_2 										Segment_2;
	typedef typename Regular_triangulation_2::Locate_type 					Locate_type;
	typedef typename Regular_triangulation_2::Bare_point 					Bare_point;
	typedef typename std::list<Edge>::iterator  							OutputItEdges;

	scope* In_Regular_triangulation_2 = new scope(
    class_< Regular_triangulation_2 >("Regular_triangulation_2",init<>())
		.def(init< const Regular_triangulation_2& >())
        .def("is_valid", &Regular_triangulation_2::is_valid, is_valid_overloads_0_2())
		.def("insert", (Vertex_handle (Regular_triangulation_2::*)(const Weighted_point&, Face_handle) )&Regular_triangulation_2::insert, insert_overloads_1_2())
		.def("insert", (Vertex_handle (Regular_triangulation_2::*)(const Weighted_point&, Locate_type, Face_handle, int) )&Regular_triangulation_2::insert)
		.def("insert", &py_insert<Regular_triangulation_2>)
		.def("push_back", &Regular_triangulation_2::push_back)
		.def("remove", &Regular_triangulation_2::remove)
		.def("number_of_vertices", &Regular_triangulation_2::number_of_vertices,"returns the number of finite vertices that are not hidden.")
		.def("number_of_hidden_vertices", &Regular_triangulation_2::number_of_hidden_vertices,"returns the number of hidden vertices.")
		.def("weighted_circumcenter", (Point_2 (Regular_triangulation_2::*)(Face_handle f) const)&Regular_triangulation_2::weighted_circumcenter)
       	.def("dual", (Point_2 (Regular_triangulation_2::*)(Face_handle) const)&Regular_triangulation_2::dual)
        .def("dual", &dual<kernel,Regular_triangulation_2,Edge>)
		.def("get_conflicts",&py_get_conflicts<Regular_triangulation_2,Point_2,Face_handle>)
		.def("get_boundary_of_conflicts",&py_get_boundary_of_conflicts<Regular_triangulation_2,Point_2,Face_handle,Edge>)
 		.def("get_hidden_vertices", &py_get_hidden_vertices<Regular_triangulation_2,Weighted_point,Face_handle>)
		.add_property("hidden_vertices", &py_hidden_vertices<Hidden_vertices_iterator,Vertex_handle,Regular_triangulation_2>)
		.add_property("vertices", &py_vertices<Vertex_iterator,Vertex_handle,Regular_triangulation_2>)
		.add_property("all_vertices",  &py_all_vertices<All_vertices_iterator,Vertex_handle,Regular_triangulation_2>)

//============================ functions inherted from Triangulation_2 ==================
/*		.def("swap", &Regular_triangulation_2::swap,Regular_2_docs[swap_doc])*/
		.def("clear", &Regular_triangulation_2::clear,Regular_2_docs[clear_doc])
        .def("dimension", &Regular_triangulation_2::dimension,Regular_2_docs[dimension_doc])
        .def("number_of_vertices", &Regular_triangulation_2::number_of_vertices,Regular_2_docs[number_of_vertices_doc])
        .def("number_of_faces", &Regular_triangulation_2::number_of_faces,Regular_2_docs[number_of_faces_doc])
        .def("infinite_vertex", &Regular_triangulation_2::infinite_vertex,Regular_2_docs[infinite_vertex_doc])
        .def("finite_vertex", &Regular_triangulation_2::finite_vertex,Regular_2_docs[finite_vertex_doc])
        .def("infinite_face", &Regular_triangulation_2::infinite_face,Regular_2_docs[infinite_face_doc])
        .def("infinite_tester", &Regular_triangulation_2::infinite_tester,Regular_2_docs[infinite_tester_doc])
        .def("set_infinite_vertex", &Regular_triangulation_2::set_infinite_vertex)

        .def("is_infinite", (bool (Regular_triangulation_2::*)(Vertex_handle) const)&Regular_triangulation_2::is_infinite)
        .def("is_infinite", (bool (Regular_triangulation_2::*)(Face_handle, int) const)&Regular_triangulation_2::is_infinite)
        .def("is_infinite", (bool (Regular_triangulation_2::*)(const Edge&) const)&Regular_triangulation_2::is_infinite)
        .def("is_edge", (bool (Regular_triangulation_2::*)(Vertex_handle, Vertex_handle) const)&Regular_triangulation_2::is_edge,Regular_2_docs[is_edge_doc])
        .def("is_edge", (bool (Regular_triangulation_2::*)(Vertex_handle, Vertex_handle, Face_handle&, int&) const)&Regular_triangulation_2::is_edge)
        .def("includes_edge", &Regular_triangulation_2::includes_edge)
        .def("is_face", (bool (Regular_triangulation_2::*)(Vertex_handle, Vertex_handle, Vertex_handle) const)&Regular_triangulation_2::is_face,Regular_2_docs[is_face_doc])
        .def("is_face", (bool (Regular_triangulation_2::*)(Vertex_handle, Vertex_handle, Vertex_handle, Face_handle&) const)&Regular_triangulation_2::is_face)
        .def("triangle", &Regular_triangulation_2::triangle,Regular_2_docs[triangle_doc])
        .def("segment", (Segment_2 (Regular_triangulation_2::*)(Face_handle, int) const)&Regular_triangulation_2::segment,Regular_2_docs[segment_doc])
        .def("segment", (Segment_2 (Regular_triangulation_2::*)(const Edge&) const)&Regular_triangulation_2::segment)
        .def("segment", (Segment_2 (Regular_triangulation_2::*)(const Finite_edges_iterator&) const)&Regular_triangulation_2::segment)
        .def("circumcenter", (Weighted_point (Regular_triangulation_2::*)(Face_handle) const)&Regular_triangulation_2::circumcenter,Regular_2_docs[circumcenter_doc])
        .def("circumcenter", (Weighted_point (Regular_triangulation_2::*)(const Weighted_point&, const Weighted_point&, const Weighted_point&) const)&Regular_triangulation_2::circumcenter)
        .def("flip", &Regular_triangulation_2::flip,Regular_2_docs[flip_doc])
        .def("insert_first", &Regular_triangulation_2::insert_first,Regular_2_docs[insert_first_doc])
        .def("insert_second", &Regular_triangulation_2::insert_second,Regular_2_docs[insert_second_doc])
        .def("insert_in_edge", &Regular_triangulation_2::insert_in_edge,Regular_2_docs[insert_in_edge_doc])
        .def("insert_in_face", &Regular_triangulation_2::insert_in_face,Regular_2_docs[insert_in_face_doc])
        .def("insert_outside_convex_hull", &Regular_triangulation_2::insert_outside_convex_hull,Regular_2_docs[insert_outside_convex_hull_doc])
        .def("insert_outside_affine_hull", &Regular_triangulation_2::insert_outside_affine_hull)
        .def("remove_degree_3", &Regular_triangulation_2::remove_degree_3, remove_degree_3_overloads_1_2())
        .def("remove_first", &Regular_triangulation_2::remove_first,Regular_2_docs[remove_first_doc])
        .def("remove_second", &Regular_triangulation_2::remove_second,Regular_2_docs[remove_second_doc])
		// add the documentation to this function.
        .def("locate", &py_locate<Regular_triangulation_2,Face_handle,Point_2>)

        .def("locate", (Face_handle (Regular_triangulation_2::*)(const Weighted_point&, Face_handle) const)&Regular_triangulation_2::locate, locate_overloads_1_2())
      	.def("incident_faces", &py_incident_faces<Face_circulator,Face_handle,Vertex_handle,Regular_triangulation_2>,Regular_2_docs[incident_faces_doc])
      	.def("incident_faces", &py_incident_faces_2<Face_circulator,Vertex_handle,Face_handle,Regular_triangulation_2>)
      	.def("incident_edges", &py_incident_edges<Edge_circulator,Vertex_handle,Regular_triangulation_2>,Regular_2_docs[incident_edges_doc])
      	.def("incident_edges", &py_incident_edges_2<Edge_circulator,Vertex_handle,Face_handle,Regular_triangulation_2>)
      	.def("incident_vertices", &py_incident_vertices<Vertex_circulator,Vertex_handle,Regular_triangulation_2>,Regular_2_docs[incident_vertices_doc])
      	.def("incident_vertices", &py_incident_vertices_2<Vertex_circulator,Vertex_handle,Face_handle,Regular_triangulation_2>)
        .def("line_walk", &py_line_walk<Line_face_circulator,Point_2,Regular_triangulation_2>)
        .def("line_walk", &py_line_walk_2<Line_face_circulator,Point_2,Face_handle,Regular_triangulation_2>)
     	.add_property("faces", &py_faces<Finite_faces_iterator,Face_handle,Regular_triangulation_2>)
        .add_property("edges", &py_edges<Finite_edges_iterator,Regular_triangulation_2>)
        .add_property("points", &py_points<Point_iterator,Regular_triangulation_2>)
        .add_property("all_faces", &py_all_faces<All_faces_iterator,Face_handle,Regular_triangulation_2>)
        .add_property("all_edges", &py_all_edges<All_edges_iterator,Regular_triangulation_2>)
        .def("ccw", &CGAL::Triangulation_cw_ccw_2::ccw,Regular_2_docs[ccw_doc])
        .def("cw", &CGAL::Triangulation_cw_ccw_2::cw,Regular_2_docs[cw_doc])

        .staticmethod("ccw")
        .staticmethod("cw")
	);
    enum_< Locate_type >("Locate_type")
        .value("OUTSIDE_CONVEX_HULL", Regular_triangulation_2::OUTSIDE_CONVEX_HULL)
        .value("EDGE", Regular_triangulation_2::EDGE)
        .value("VERTEX", Regular_triangulation_2::VERTEX)
        .value("OUTSIDE_AFFINE_HULL", Regular_triangulation_2::OUTSIDE_AFFINE_HULL)
        .value("FACE", Regular_triangulation_2::FACE)
    ;

    delete In_Regular_triangulation_2;

//BEGIN ==================== TOOLS OF Regular_triangulation_2 =====================================
    class_< CGAL::Weighted_point<Point_2,double>, bases< Point_2 >  >("Weighted_point", init<  >())
        .def(init< const CGAL::Weighted_point<Point_2,double>& >())
        .def(init< const Point_2& >())
        .def(init< const Point_2&, const double& >())
        .def("point", &CGAL::Weighted_point<Point_2,double>::point, return_value_policy< copy_const_reference >())
        .def("weight", &CGAL::Weighted_point<Point_2,double>::weight, return_value_policy< copy_const_reference >())
    ;

	class_<Vertex_handle>("Vertex",init<>())
		.def(init< const Vertex_iterator& >()) 
		.def(self==self)
		.def(self!=self)
		.def(self < self)
		.def("point",&point<Vertex_handle>)
		.def("is_valid",&is_valid<Vertex_handle>)
		.def("set_point",&set_point<Vertex_handle,Point_2>)
		.def("set_info",&set_info<Vertex_handle>)
		.def("info",&py_info<Vertex_handle>)
		.def("degree",&degree<Vertex_handle>)
	;

	class_<Face_handle>("Face",init<>())
		.def(init< const Face_iterator& >()) 
		.def(self==self)
		.def(self!=self)
		.def(self < self)
		.def("ccw",&py_ccw<Face_handle>)
		.def("cw",&py_cw<Face_handle>)
		.def("mirror_vertex",&py_mirror_vertex<Face_handle,Vertex_handle>)
 		.def("mirror_index",&py_mirror_index<Face_handle>)
		.def("vertex",&py_vertex<Face_handle,Vertex_handle>)
		.def("has_vertex",&py_has_vertex1<Face_handle,Vertex_handle>)
		.def("has_vertex",&py_has_vertex2<Face_handle,Vertex_handle>)
		.def("index",&py_index1<Face_handle,Vertex_handle>)
		.def("index",&py_index2<Face_handle>)
		.def("neighbor",&py_neighbor<Face_handle>)
		.def("has_neighbor",&py_has_neighbor1<Face_handle>)
		.def("has_neighbor",&py_has_neighbor2<Face_handle>)
		.def("set_vertices",&py_set_vertices1<Face_handle>)
		.def("set_vertices",&py_set_vertices2<Face_handle,Vertex_handle>)
		.def("set_vertex",&py_set_vertex<Face_handle,Vertex_handle>)
		.def("set_neighbor",&py_set_neighbor<Face_handle>)
		.def("set_neighbors",&py_set_neighbors1<Face_handle>)
		.def("set_neighbors",&py_set_neighbors2<Face_handle>)
		.def("reorient",&py_reorient<Face_handle>)
		.def("ccw_permute",&py_ccw_permute<Face_handle>)
		.def("cw_permute",&py_cw_permute<Face_handle>)
		.def("dimension",&py_dimension<Face_handle>)
	;

	Handle_to_py_iterator<Vertex_iterator,Vertex_handle>::declare("Vertex_iterator");
	Handle_to_py_iterator<Face_iterator,Face_handle>::declare("Face_iterator");
	simple_python_iterator<Edge_iterator>::declare("Edge_iterator");
// 	simple_python_iterator<Point_iterator>::declare("Point_iterator");

	circulator_to_py_iterator<Face_circulator,Face_handle>::declare("Face_circulator");
	simple_python_circulator<Edge_circulator>::declare("Edge_circulator");
	circulator_to_py_iterator<Vertex_circulator,Vertex_handle>::declare("Vertex_circulator");

//END ==================== TOOLS OF Regular_triangulation_2 =====================================

}


void export_Regular_triangulation_2()
{
	Py_Regular_triangulation_2<K>();
}
